package com.wwg.util;

import com.wwg.component.MyApplicationContextAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description 获取bean的工厂类
 * @systemName 融资平台
 * @author yyh
 * @date 2019年5月7日 下午4:50:43
 * @version V1.0
 */
public class WWGBeanFactory {
	private static final Logger LOG = LoggerFactory.getLogger(WWGBeanFactory.class);
	private static final Map<Class<?>, Object> cacheMap = new ConcurrentHashMap<Class<?>, Object>();

	private WWGBeanFactory() {
	}

	public static <T> T getBean(Class<T> requiredType) {
		return MyApplicationContextAware.getApplicationContext().getBean(requiredType);
	}

	public static <T> T getBean(String name, Class<T> requiredType) {
		return MyApplicationContextAware.getApplicationContext().getBean(name, requiredType);
	}

	public static Object getBean(String name) {
		return MyApplicationContextAware.getApplicationContext().getBean(name);
	}

	public static <T> Map<String, T> getBeansOfType(Class<T> requiredType) {
		return MyApplicationContextAware.getApplicationContext().getBeansOfType(requiredType);
	}

//	/**
//	 * @description 获取非springboot工程下远程服务
//	 * @param requiredType
//	 * @return
//	 * @author yyh
//	 * @date 2019年5月15日 下午4:48:16
//	 */
//	public static <T> T getReference(Class<T> requiredType) {
//		T referenceBean = (T) cacheMap.get(requiredType);
//		if (!WWGAssertUtil.isEmpty(referenceBean)) {
//			return referenceBean;
//		}
//		try {
//			referenceBean = getBean(requiredType);
//			if (!WWGAssertUtil.isEmpty(referenceBean)) {
//				cacheMap.put(requiredType, referenceBean);
//			}
//		} catch (Exception e) {
//			if (e instanceof NoSuchBeanDefinitionException) {
//				try{
//					ApplicationConfig applicationConfig = getBean(ApplicationConfig.class);
//					RegistryConfig registryConfig = WWGBeanFactory.getBean(RegistryConfig.class);
//					ReferenceConfig<T> rc = new ReferenceConfig<T>();
//					rc.setApplication(applicationConfig);
//					rc.setRegistry(registryConfig);
//					rc.setInterface(requiredType);
//					referenceBean = rc.get();
//					if (!WsnAssert.isEmpty(referenceBean)) {
//						cacheMap.put(requiredType, referenceBean);
//					}
//				}catch(Throwable e1){
//					LOG.error(e1.getMessage(), e1);
//				}
//			} else {
//				LOG.error(e.getMessage(), e);
//			}
//		}
//		return referenceBean;
//	}

//	/**
//	 * @description 获取springboot工程下远程服务
//	 * @param requiredType
//	 * @return
//	 * @author yyh
//	 * @date 2019年5月15日 下午4:49:09
//	 */
//	public static <T> T getBootReference(Class<T> requiredType) {
//		T referenceBean = (T) cacheMap.get(requiredType);
//		if (!WsnAssert.isEmpty(referenceBean)) {
//			return referenceBean;
//		}
//		try {
//			referenceBean = getBean(requiredType);
//			if (!WsnAssert.isEmpty(referenceBean)) {
//				cacheMap.put(requiredType, referenceBean);
//			}
//		} catch (Exception e) {
//			if (e instanceof NoSuchBeanDefinitionException) {
//				Class<?> clasz = null;
//				try {
//					clasz = Class.forName("com.alibaba.dubbo.spring.boot.DubboProperties");
//				} catch (ClassNotFoundException e1) {
//					LOG.error(e1.getMessage(), e1);
//				}
//
//				Object dubboPropertiesBean = getBean(clasz);
//				ApplicationConfig applicationConfig = (ApplicationConfig) getMethodReturnByReflex(dubboPropertiesBean,
//						"getApplication");
//				RegistryConfig registryConfig = (RegistryConfig) getMethodReturnByReflex(dubboPropertiesBean,
//						"getRegistry");
//				ReferenceConfig<T> rc = new ReferenceConfig<T>();
//				rc.setApplication(applicationConfig);
//				rc.setRegistry(registryConfig);
//				rc.setInterface(requiredType);
//				referenceBean = rc.get();
//				cacheMap.put(requiredType, referenceBean);
//			} else {
//				LOG.error(e.getMessage(), e);
//			}
//		}
//		return referenceBean;
//	}

	private static Object getMethodReturnByReflex(Object bean, String methodName) {
		Method method = null;
		Class<?> clasz = bean.getClass();
		Method[] methods = clasz.getDeclaredMethods();
		if (methods != null && methods.length > 0) {
			for (int i = 0; i < methods.length; i++) {
				if (methods[i].getName().equals(methodName)) {
					method = methods[i];
					break;
				}
			}
		}
		try {
			Object ret = method.invoke(bean);
			return ret;
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
		return null;
	}
}
